package com.wind.cloud.common.config.transaction;

import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttribute;

import java.lang.reflect.Method;
import java.util.Properties;

/**
 * IService类及子类都自动加上事务（避免事务遗忘）
 *
 * @author wind.
 */
public class TransactionServiceAttributeSource extends AnnotationTransactionAttributeSource {

    @Override
    @Nullable
    protected TransactionAttribute findTransactionAttribute(Method method) {
        // 优先注解事务
        TransactionAttribute transactionAttribute = determineTransactionAttribute(method);

        if (transactionAttribute == null) {
            // IService类及子类
            if (ITxService.class.isAssignableFrom(method.getDeclaringClass()) || IService.class.isAssignableFrom(method.getDeclaringClass())) {
                transactionAttribute = getNameMatchTransactionAttributeSource().getTransactionAttribute(method, method.getDeclaringClass());
            }
        }

        return transactionAttribute;
    }

    private NameMatchTransactionAttributeSource getNameMatchTransactionAttributeSource() {
        NameMatchTransactionAttributeSource nameMatchTransactionAttributeSource = new NameMatchTransactionAttributeSource();
        Properties properties = new Properties();
        properties.setProperty("insert*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");
        properties.setProperty("add*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");
        properties.setProperty("save*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");
        properties.setProperty("update*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");
        properties.setProperty("del*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");
        properties.setProperty("remove*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");
        properties.setProperty("execute*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable");

        properties.setProperty("*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable,readOnly");
        nameMatchTransactionAttributeSource.setProperties(properties);
        return nameMatchTransactionAttributeSource;
    }

}
